home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / unix / tar / part01 next >
Encoding:
Internet Message Format  |  1990-03-29  |  58.8 KB

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i126: tar - tape archive utility, Part01/05
  5. Message-ID: <11979@xanth.cs.odu.edu>
  6. Date: 29 Mar 90 03:08:05 GMT
  7. Sender: tadguy@cs.odu.edu
  8. Reply-To: hue@netcom.uucp (Jonathan Hue)
  9. Lines: 2011
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11. X-Mail-Submissions-To: Amiga@cs.odu.edu
  12. X-Post-Discussions-To: comp.sys.amiga
  13.  
  14. Submitted-by: hue@netcom.uucp (Jonathan Hue)
  15. Posting-number: Volume 90, Issue 126
  16. Archive-name: unix/tar/part01
  17.  
  18. I finally found the time to finish and test this program.  This is tar
  19. for the Amiga, fully compatible with UNIX tar, plus some Amiga enhancements,
  20. such as preservation of all mode bits, comments, and timestamp down to
  21. ticks.  This is based on John Gilmore's public domain tar.
  22.  
  23. Mail bug reports to me and I'll fix them.  
  24.  
  25. -Jonathan
  26. apple!netcom!hue
  27.  
  28. #!/bin/sh
  29. # This is a shell archive.  Remove anything before this line, then unpack
  30. # it by saving it into a file and typing "sh file".  To overwrite existing
  31. # files, type "sh file -c".  You can also feed this as standard input via
  32. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  33. # will see the following message at the end:
  34. #        "End of archive 1 (of 5)."
  35. # Contents:  Makefile PORTING README README.1st README.AMIGA TODO
  36. #   amiga.c diffarch.c dir.c dirent.h getoldopt.c getopt.c open3.h
  37. #   port.h stat.h tar.h tar.lnk types.h utime.c wildmat.c
  38. # Wrapped by tadguy@xanth on Wed Mar 28 22:07:07 1990
  39. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  40. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  41.   echo shar: Will not clobber existing file \"'Makefile'\"
  42. else
  43. echo shar: Extracting \"'Makefile'\" \(345 characters\)
  44. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  45. XCC = lc
  46. XCFLAGS = -O -DNONAMES -DDEFBLOCKING=20
  47. X
  48. XSRCS = buffer.c create.c diffarch.c extract.c getoldopt.c getopt.c list.c \
  49. X    port.c tar.c utime.c wildmat.c amiga.c
  50. X
  51. XOBJS = buffer.o create.o diffarch.o extract.o getoldopt.o getopt.o list.o \
  52. X    port.o tar.o utime.o wildmat.o amiga.o
  53. X
  54. Xall:    tar
  55. X
  56. Xtar:    $(OBJS)
  57. X    blink with tar.lnk
  58. X
  59. Xclean:
  60. X    rm *.o tar
  61. END_OF_FILE
  62. if test 345 -ne `wc -c <'Makefile'`; then
  63.     echo shar: \"'Makefile'\" unpacked with wrong size!
  64. fi
  65. # end of 'Makefile'
  66. fi
  67. if test -f 'PORTING' -a "${1}" != "-c" ; then 
  68.   echo shar: Will not clobber existing file \"'PORTING'\"
  69. else
  70. echo shar: Extracting \"'PORTING'\" \(2963 characters\)
  71. sed "s/^X//" >'PORTING' <<'END_OF_FILE'
  72. X        Porting hints for public domain tar
  73. X          John Gilmore, ihnp4!hoptoad!gnu
  74. X             @(#)PORTING 1.13    87/11/11
  75. X
  76. XThe Makefile should be edited to comment out all the undesired
  77. Xversions, and create the following configuration lines for the system
  78. Xyou are compiling it on:
  79. X
  80. XDEFS = the proper #define's to conditionally compile for your system.
  81. XLIBS = the system libraries and/or object modules to link with the program.
  82. XLINT = the lint program (or the compiler with extra checking turned on)
  83. XLINTFLAGS = a good strong way to invoke 'lint' on your system.
  84. XDEF_AR_FILE = the name of the default archive file on your system.
  85. X    It should be enclosed in quoted quotes, e.g. \"/dev/foo\" .
  86. XDEFBLOCKING = the default blocking factor on your system.
  87. XO = the suffix for object files ('o', except 'obj' for MSDOS).
  88. X
  89. XA copy of "getopt", the standard argument parser, is required.  It's in
  90. Xlibc on Missed'em V systems and 4.3BSD; on most other systems, you'll
  91. Xneed a copy of a public domain getopt, available through the
  92. Xcomp.sources.unix archives, or from the AT&T Toolchest if you can't
  93. Xfind it elsewhere.
  94. X
  95. XA copy of the Berkeley directory access routines is also required.
  96. XThese are in libc and <sys/dir.h> on Berkeley systems.  A public domain
  97. Xversion is available through comp.sources.unix.  There is an #include
  98. Xyou have to change in create.c for this, to set the name of the include
  99. Xfile you have.  Some systems have the include file in <sys/ndir.h>.
  100. XYou'll have to find it on your system, or get the public domain one and
  101. Xplace it somewhere.  For MSDOS, I have supplied these directory
  102. Xroutines in msd_dir.c and msd_dir.h, since it's likely that your system
  103. Xdoesn't have them.  To permanently install these into your MSC 3.0
  104. Xlibrary, do the following:
  105. X    copy msd_dir.h c:\c\include\sys\dir.h
  106. X    cl -A$(MODEL) -c msd_dir.c
  107. X    lib $(MODEL)dir.lib msd_dir.obj;
  108. XChange c:\c\include to wherever your standard include directory is.
  109. XYou might have to modify this procedure if you aren't using MSC 3.0. 
  110. X
  111. XGrep for FIXME to find places that aren't finished or which have
  112. Xportability problems.  Also see the file TODO.
  113. X
  114. XThe MSDOS port was done under the Microsoft C 3.0 compiler and
  115. Xlibraries.  In the Makefile, COPTS should be changed to -Zi or nothing;
  116. Xand there is a special link command for making tar.exe, which you will
  117. Xhave to uncomment, since MSDOS can't handle command lines longer than
  118. X128 bytes.  Also, clean and install will not work unless you change
  119. X/ in path names to \.
  120. X
  121. XOn Minix, there are a bunch of problems.  "V7 compatible" my ass.
  122. X * "make" doesn't expand macros in the Makefile properly.  You will
  123. Xprobably have to expand them by hand.  Better to go in and fix Minix
  124. X"make" though...
  125. X * The directory access library is nonexistent.  It wasn't in V7 but
  126. Xanybody who writes code without it, even on V7 systems, is a fool.
  127. X * Various other library routines are broken, e.g. printf() doesn't take
  128. X"%*s" or "%.*s"; no <sys/types.h> which Unix requires, ctime(), getopt().
  129. END_OF_FILE
  130. if test 2963 -ne `wc -c <'PORTING'`; then
  131.     echo shar: \"'PORTING'\" unpacked with wrong size!
  132. fi
  133. # end of 'PORTING'
  134. fi
  135. if test -f 'README' -a "${1}" != "-c" ; then 
  136.   echo shar: Will not clobber existing file \"'README'\"
  137. else
  138. echo shar: Extracting \"'README'\" \(2695 characters\)
  139. sed "s/^X//" >'README' <<'END_OF_FILE'
  140. XThis is the Nov87 release of a public domain tar(1) replacement.  It
  141. Ximplements the 'c', 'x', and 't' commands of Unix tar, and many of the
  142. Xoptions.  It creates P1003 "Unix Standard" [draft 6] tapes by default,
  143. Xand can read and write both old and new formats.  It can compress or
  144. Xdecompress tar archives "on the fly" (using the 'z' option) as well as
  145. Xaccessing remote tape drives or files by specifying
  146. X"host:/dev/tapedrive".  It lets you set the default tape drive by
  147. Xsetting TAPE in your environment.  Its verbose output looks more like
  148. X"ls -l" than the Unix tar, the columns line up, and you can get verbose
  149. Xlistings from the 'cvv' option as well as from 'xvv' and 'tv'.  It does
  150. Xshell-globbing (regular expressions) for listing and extraction.  It is
  151. Xa little better at reading damaged tapes than Unix tar.  There is a
  152. Xhalf-baked "diff" option for comparing a tape against the file system.
  153. XAnd it's free.
  154. X
  155. XIt is designed to be a lot more efficient than the standard Unix tar;
  156. Xit does as little bcopy-ing as possible, and does file I/O in large
  157. Xblocks.  On the other hand, it has not been timed or performance-tuned;
  158. Xit's just *designed* to be faster.
  159. X
  160. XOn SunOS 3.3, the tar archives it creates under the 'old' option are
  161. Xbyte-for-byte the same as those created by /bin/tar, except the trash
  162. Xat the end of each file and at the end of the archive has been replaced
  163. Xby zeroes.
  164. X
  165. XIt was written and initially debugged on a Sun Workstation running
  166. X4.2BSD.  It has been run on Xenix, Unisoft, Vax 4.2BSD, utzoonix, USG,
  167. XMasscomp, Minix, and MSDOS systems.  I'm interested in finding people
  168. Xwho will port it to other types of (Unix and non-Unix) systems, use it,
  169. Xand send back the changes; and people who will add the obscure tar
  170. Xoptions that they happen to use and I don't.  In particular, VMS, Mac,
  171. XAtari and Amiga versions would be handy.
  172. X
  173. XIt still has a number of loose ends, marked by "FIXME" comments in the
  174. Xsource.  Fixes to these things are also welcome.
  175. X
  176. XI am the author of all the code in this program, except some of the
  177. Xsubroutines, which are from contributors listed below.  I hereby place
  178. Xit in the public domain.  If you modify it, or port it to another
  179. Xsystem, please send me back a copy, so I can keep a master source.
  180. X
  181. XThis program is much better than it started, due to the effort and care
  182. Xput in by Henry Spencer, Fred Fish, Ian Darwin, Geoff Collyer, Stan
  183. XBarber, Guy Harris, Dave Brower, Richard Todd, Michael Rendell, Stu
  184. XHeiss, and Rich $alz.  Thank you, one and all.
  185. X
  186. X    John Gilmore
  187. X    Nebula Consultants
  188. X    PO Box 170608
  189. X    San Francisco, California, USA  94117-0608
  190. X    hoptoad!gnu    or   gnu@toad.com
  191. X    Hoptoad talks to sun, ptsfa, ihnp4, utzoo, ucsfcgl.
  192. X
  193. X@(#)README 1.14    87/11/11
  194. END_OF_FILE
  195. if test 2695 -ne `wc -c <'README'`; then
  196.     echo shar: \"'README'\" unpacked with wrong size!
  197. fi
  198. # end of 'README'
  199. fi
  200. if test -f 'README.1st' -a "${1}" != "-c" ; then 
  201.   echo shar: Will not clobber existing file \"'README.1st'\"
  202. else
  203. echo shar: Extracting \"'README.1st'\" \(322 characters\)
  204. sed "s/^X//" >'README.1st' <<'END_OF_FILE'
  205. X
  206. XIf you want to make tar, you'll have to move some files around because
  207. XI grabbed some .h and dirlib.c from other directories and put them here.
  208. X
  209. XYou'll get some warning when compiling because I never got around to
  210. Xgoing back and casting the return values from some functions which
  211. Xwere declared to return BPTR.
  212. X
  213. X-Jonathan
  214. END_OF_FILE
  215. if test 322 -ne `wc -c <'README.1st'`; then
  216.     echo shar: \"'README.1st'\" unpacked with wrong size!
  217. fi
  218. # end of 'README.1st'
  219. fi
  220. if test -f 'README.AMIGA' -a "${1}" != "-c" ; then 
  221.   echo shar: Will not clobber existing file \"'README.AMIGA'\"
  222. else
  223. echo shar: Extracting \"'README.AMIGA'\" \(3736 characters\)
  224. sed "s/^X//" >'README.AMIGA' <<'END_OF_FILE'
  225. XAmiga Tar
  226. X
  227. XThis is tar for the Amiga.  I used John Gilmore's (gnu@toad.COM) public
  228. Xdomain tar program as a base for this tar.  This program, and the files it
  229. Xproduces are supposed to be fully compatible with UNIX tar.
  230. X
  231. XAmiga Specific Features
  232. X
  233. XThere are a couple of Amiga specific features which I've added.  In an unused
  234. Xpart of the header I store a magic number, the original Amiga file bits, the
  235. Xfile's date stamp (including ticks), and the file comment.  When this program
  236. Xextracts it looks for the magic number.  If it is present, it uses the stored
  237. Xfile bits to set the mode rather than the mode stored in the regular tar
  238. Xheader.  The file's comment is also set, and the timestamp set from the
  239. Xoriginal timestamp.  There is also some filename translation which goes on,
  240. Xeach leading / translates to ../, null string translates to ./, so the files
  241. Xare compatible with UNIX.  The reverse of these translations is done when
  242. Xextracting.  Since some shells have difficulty giving tar a null string as an
  243. Xargument, "." can be used to specify the current directory, as in
  244. X"tar cvf ram:mybackup ." to add every file in and below the current directory
  245. Xto the tar archive.  You may need to quote the single period in some shells,
  246. Xlike Sksh, as it will expand to the absolute pathname otherwise.
  247. X
  248. XArchiving
  249. X
  250. XIf you specify the modifier "a" on the command line, the archived bit of every
  251. Xfile will be set as it is added to the tar archive.  You can use tar as a file
  252. Xbackup utility this way.  Regardless of command line options, the archived bit
  253. Xis always cleared upon extraction.
  254. X
  255. XIf you specify the modifier "A" on the command line, tar will not archive
  256. Xany regular file which has its archived bit set.  Directories are always
  257. Xwritten to the archive.
  258. X
  259. XDifferences
  260. X
  261. XIf you say something like "tar cvf ram:foo .", the output might not be what
  262. Xyou would expect.  To get the normal amount of verbosity, you need to specify
  263. X"v" twice, as in "tar cvvf ram:foo".  I think the reason this was done is so
  264. Xthat a single v will give you a list of filenames you can easily edit,
  265. Xsomething a normal tar won't do.  You should also realize that you can't
  266. Xset protection, comment, or datestamp on a root directory.  Tar can fail when
  267. Xsetting protection, comment, and datestamp on a directory.  This will happen
  268. Xif someone is holding a lock on the directory.  Tar tries to be clever
  269. Xand cd up one level when setting stuff on the current directory, but this
  270. Xwill fail if anyone else has a lock on the directory.  Tar complains loudly
  271. Xwhen this happens.  Tar works with CrossDOS, but setting the comment fails
  272. Xof course.
  273. X
  274. XEnvironment variables
  275. X
  276. XYou will want to set a couple environment variables for tar.  You should set
  277. XTZ, just like in UNIX.  For me the command line is "setenv TZ PST8PDT".
  278. XIf you don't set TZ, tar uses "CST6CDT" as the default.  The second
  279. Xenvironment variable is "TARFILE", which is the name of the default
  280. Xfile to create.  You should do something like "setenv TARFILE ram:tarfile".
  281. XIf you don't set TARFILE, it defaults to "ram:tarfile".
  282. X
  283. XWhy tar?
  284. X
  285. XThere are a lot of reasons for using tar.  It preserves the directory
  286. Xstructure, it's fast, it restores all the information that goes along
  287. Xwith a file, and it's used on UNIX boxes.
  288. X
  289. XBugs
  290. X
  291. XWhile I've tried to test this as much I can, I can't guarantee that there
  292. Xaren't any bugs.  So use this at your own risk.  
  293. X
  294. XFor reasons I don't understand, tar cannot set the timestamp on files in
  295. Xthe current directory when the files reside on the ASDG recoverable RAM
  296. XDISK.  It works fine with everything else I've tried.  If you look at the
  297. Xcode in utime.c, the ParentDir() call returns zero.  The files are still
  298. Xextracted ok, but the timestamps are not changed.
  299. X
  300. XJonathan Hue
  301. Xhue@netcom.UUCP
  302. END_OF_FILE
  303. if test 3736 -ne `wc -c <'README.AMIGA'`; then
  304.     echo shar: \"'README.AMIGA'\" unpacked with wrong size!
  305. fi
  306. # end of 'README.AMIGA'
  307. fi
  308. if test -f 'TODO' -a "${1}" != "-c" ; then 
  309.   echo shar: Will not clobber existing file \"'TODO'\"
  310. else
  311. echo shar: Extracting \"'TODO'\" \(2713 characters\)
  312. sed "s/^X//" >'TODO' <<'END_OF_FILE'
  313. X@(#) TODO 1.15 87/11/06
  314. X
  315. XTest owner/group on extraction better.
  316. X
  317. Xcreation of links, symlinks, nodes doesn't follow the -k (f_keep) guidelines;
  318. Xif the file already exists, it is not replaced, even though no -k.
  319. X
  320. XCheck stderr and stdout for errors after writing, and quit if so.
  321. X
  322. XPreliminary design of Multifile option to handle EOFs on input and
  323. Xoutput.  Multifile can just close the archive when it hits end of
  324. Xarchive, and ask for archive to be changed.  It has no choice on some
  325. Xmedia, e.g. floppies and cartridge tapes, where there is no room for an
  326. XEOF block there.  Start off 2nd archive medium with odd header block,
  327. Xduplicating original, but with offset to start of data spec'd.  Reading
  328. Xsuch a header causes tar non-'M' to complain while extracting (but to
  329. Xseek there and do it anyway!)  Big win -- this works on cartridge
  330. Xtapes, should work on floppies, might work on magtape.  It would
  331. Xencourage the *&%#$ systems programmers to fix their drivers, too!
  332. X
  333. XProfile it and see where the time, call counts, etc are going.
  334. X
  335. XFix directory timestamps after inserting files into them.  Wait til next
  336. Xfile that's not in the directory.  Need a stack of them.
  337. X
  338. XOption to seek the input file (in skip_file) rather than reading
  339. Xand tossing it?  (Could just jump in buffer if stuff is in core.)
  340. XCould misalign archive reads versus filesys and slow it down, who knows?
  341. X
  342. XAdd -C option for creating from odd directories a la 4.2BSD?
  343. X
  344. XBreak out odd bits of code into separate support modules.
  345. X
  346. XAdd the r, u, X, l, F, C, and digit options of Unix tar.
  347. X
  348. XV8 tar does something that is quite handy when reading tapes written on
  349. X4.2 system into non-4.2 systems: it reduces file name components to
  350. X14 bytes or less and ensures that they are unique (I think it truncates
  351. Xto 10 bytes and appends "..aa" where aa are two unique letters) and puts
  352. Xout a file containing the mapping between long names on tape and short
  353. Xnames on disk.
  354. X
  355. XClean up 'd' (diff) option.  Currently it works for regular files
  356. Xand symlinks, needs work for dirs and links.  Ideally, output should
  357. Xlook like "diff -r" or -rl after an extract of the tape and a real diff.
  358. XRight now it's very messy.  To do the above, we'd need to read the
  359. Xdirectories that we touch and check all the file names against what's
  360. Xon the tape.  All we do now is check the file contents and stats.
  361. X
  362. XCheck "int" variables to see if they really need to be long (file sizes,
  363. Xrecord counts, etc).  Sizes of in-core buffers should be int; since
  364. Xmalloc() takes an int argument we can never allocate one any bigger.
  365. XMaybe unsigned int would be better, though.  Little system people,
  366. Xhelp me out here!  (E.g. run lint on it on your system and send me
  367. Xthe result if it shows anything fixable.)
  368. END_OF_FILE
  369. if test 2713 -ne `wc -c <'TODO'`; then
  370.     echo shar: \"'TODO'\" unpacked with wrong size!
  371. fi
  372. # end of 'TODO'
  373. fi
  374. if test -f 'amiga.c' -a "${1}" != "-c" ; then 
  375.   echo shar: Will not clobber existing file \"'amiga.c'\"
  376. else
  377. echo shar: Extracting \"'amiga.c'\" \(6424 characters\)
  378. sed "s/^X//" >'amiga.c' <<'END_OF_FILE'
  379. X#include <exec/types.h>
  380. X#include <libraries/dos.h>
  381. X#include <sys/types.h>
  382. X#include <sys/stat.h>
  383. X#include <errno.h>
  384. X#define NARGS        /* get it to shut up about my mkdir */
  385. X#include <stdio.h>
  386. X#include "tar.h"
  387. X
  388. Xumask(int mask)
  389. X{
  390. X    return (0);
  391. X}
  392. X
  393. Xstat(char *filename, struct stat * statbuf)
  394. X{
  395. X    struct FileLock *alock, *parent;
  396. X    struct FileInfoBlock *fib;
  397. X    int modes;
  398. X    extern long timezone;
  399. X
  400. X    if ((!statbuf) || (!filename))
  401. X    {
  402. X    errno = EFAULT;
  403. X    return (-1);
  404. X    }
  405. X    if (alock = Lock(filename, ACCESS_READ))
  406. X    {
  407. X    if ((fib = (struct FileInfoBlock *) malloc(sizeof(*fib))) == NULL)
  408. X    {
  409. X        UnLock(alock);
  410. X        errno = ENOMEM;
  411. X        return (-1);    /* malloc failed */
  412. X    }
  413. X    Examine(alock, fib);
  414. X    if (!(parent = ParentDir(alock)))
  415. X    {
  416. X        statbuf->st_mode = 0700;
  417. X        statbuf->st_prot = ~0xf;
  418. X    }
  419. X    else
  420. X    {
  421. X        UnLock(parent);
  422. X        modes = (~fib->fib_Protection >> 1) & 0x7;
  423. X        statbuf->st_mode = (modes << 6);
  424. X        statbuf->st_prot = fib->fib_Protection;
  425. X    }
  426. X    if (fib->fib_EntryType > 0)
  427. X        statbuf->st_mode |= S_IFDIR;
  428. X    else
  429. X        statbuf->st_mode |= S_IFREG;
  430. X    statbuf->st_dev = 0;
  431. X    statbuf->st_ino = 0;
  432. X    statbuf->st_size = fib->fib_Size;
  433. X    statbuf->st_rdev = fib->fib_DiskKey;
  434. X    statbuf->st_gid = 0;
  435. X    statbuf->st_uid = 0;
  436. X
  437. X    /*
  438. X     * getft() doesn't compensate for time zones.
  439. X     */
  440. X    statbuf->st_mtime = getft(filename) + timezone;
  441. X    statbuf->st_nlink = 1;
  442. X
  443. X    /*
  444. X     * These next fields really only exist for Amiga tar's benefit
  445. X     */
  446. X    strcpy(statbuf->st_comment, fib->fib_Comment);
  447. X    memcpy((char *) &(statbuf->st_date), (char *) &(fib->fib_Date),
  448. X           sizeof(statbuf->st_date));
  449. X    free(fib);
  450. X    UnLock(alock);
  451. X    return (0);
  452. X    } else
  453. X    {
  454. X    errno = ENOENT;
  455. X    return (-1);        /* couldn't access file */
  456. X    }
  457. X}
  458. X
  459. X
  460. X/*
  461. X * Convert Amiga style path to UNIX style. Does the following conversions:
  462. X * ull string => ./ leading /   => ../
  463. X */
  464. Xchar *
  465. XcvtAmi2UNIX(char *src, char *dst)
  466. X{
  467. X    char *dstp,
  468. X    *srcp;
  469. X
  470. X    if (!*src)
  471. X    {
  472. X    strcpy(dst, "./");
  473. X    return (dst);
  474. X    }
  475. X    dstp = dst;
  476. X    srcp = src;
  477. X/*
  478. X * Each leading / converts to ../
  479. X */
  480. X    while (*srcp == '/')
  481. X    {
  482. X    *dstp++ = '.';
  483. X    *dstp++ = '.';
  484. X    *dstp++ = '/';
  485. X    srcp++;
  486. X    }
  487. X    while (*dstp++ = *srcp++)    /* copy rest of chars */
  488. X    ;
  489. X    return (dst);
  490. X}
  491. X
  492. X/*
  493. X * Convert UNIX style path to Amiga style. Does the following conversions:
  494. X * /  => null string ../ => /
  495. X */
  496. XcvtUNIX2Ami(char *dst)
  497. X{
  498. X    char *dstp,
  499. X    *srcp,
  500. X     src[NAMSIZ + 2];
  501. X
  502. X    strcpy(src, dst);
  503. X    dstp = dst;
  504. X    srcp = src;
  505. X
  506. X    while (*srcp == '.')
  507. X    {
  508. X    if (*(srcp + 1) == '/')
  509. X        srcp += 2;        /* ./ gets skipped */
  510. X    else if ((*(srcp + 1) == '.') && (*(srcp + 2) == '/'))
  511. X    {
  512. X        srcp += 3;        /* ../ turns into / */
  513. X        *dstp++ = '/';
  514. X    } else
  515. X        break;
  516. X    }
  517. X    while (*dstp++ = *srcp++)    /* copy rest of chars */
  518. X    ;
  519. X    return (dst);
  520. X}
  521. X
  522. X
  523. X/*
  524. X * Wrapper for SetComment.  "Smart" because it knows how to handle "", and
  525. X * handle case if current directory is root.  But not so smart it can handle
  526. X * case when we're sitting in a directory it wants to SetComment on other than
  527. X * "".
  528. X */
  529. XSmartSetComment(char *filename, char *comment)
  530. X{
  531. X    extern int SetComment();
  532. X
  533. X    if (!*comment)
  534. X    return(0);
  535. X    else
  536. X    return(SmartDoSomething(filename, (int) comment, SetComment,
  537. X                "SetComment"));
  538. X}
  539. X
  540. X
  541. X/*
  542. X * Wrapper for SetProtection.  "Smart" because it knows how to handle "", and
  543. X * handle case if current directory is root.  But not so smart it can handle
  544. X * case when we're sitting in a directory it wants to SetProtection on other
  545. X * than "".
  546. X */
  547. XSmartSetProtection(char *filename, int protection)
  548. X{
  549. X    extern int SetProtection();
  550. X
  551. X    return(SmartDoSomething(filename, protection, SetProtection,
  552. X                "SetProtection"));
  553. X}
  554. X
  555. X
  556. XSmartDoSomething(char *filename, int arg, int (*doSomething)(), char *funcstr)
  557. X{
  558. X    struct FileLock *lock = 0, *parentLock;
  559. X    struct FileInfoBlock *fib = 0;
  560. X    int retval;
  561. X
  562. X    if (*filename)
  563. X    {
  564. X    if (!(*doSomething)(filename, arg))
  565. X     {
  566. X        errno = ENOENT;
  567. X        return(-1);
  568. X    }
  569. X    else
  570. X        return(0);
  571. X    }
  572. X    if (filename[strlen(filename) - 1] == ':')
  573. X    {
  574. X    errno =  EACCES;        /* root dir */
  575. X    return(-1);
  576. X    }
  577. X   /*
  578. X     * "" (current directory) case
  579. X     *
  580. X     * There are a couple things to worry about here.  First of all, you have
  581. X     * to find the parent directory, and the name of the current directory.
  582. X     * But if there is no parent, you can't set the comment.  Once you get
  583. X     * past this, you have to change directories and unlock the old current
  584. X     * directory because you can't set the protection on a busy directory.
  585. X     */
  586. X    if (!(lock = Lock("", ACCESS_READ)))
  587. X    {
  588. X    errno = ENOENT;
  589. X    return (-1);
  590. X    }
  591. X    if (!(parentLock = ParentDir(lock)))
  592. X    {
  593. X    UnLock(lock);
  594. X    errno = EACCES;        /* root dir */
  595. X    return (-1);
  596. X    }
  597. X    if (!(fib = (struct FileInfoBlock *) malloc(sizeof(*fib))))
  598. X    {
  599. X    UnLock(lock);
  600. X    errno = ENOMEM;
  601. X    return (-1);
  602. X    }
  603. X    Examine(lock, fib);
  604. X    UnLock(lock);        /* free Lock obtained by Lock("",) */
  605. X
  606. X    /*
  607. X     * At this point we have a FileInfoBlock with the name of this directory,
  608. X     * and a lock on our parent directory.  CD to the parent directory, unlock
  609. X     * the old directory, and set the comment.
  610. X     */
  611. X    lock = CurrentDir(parentLock);
  612. X    UnLock(lock);        /* free Lock held by shell??? */
  613. X    if (!(*doSomething)(fib->fib_FileName, arg))
  614. X    {
  615. X    errno = ENOENT;
  616. X    retval = -1;
  617. X    }
  618. X    else
  619. X    retval = 0;
  620. X
  621. X    /*
  622. X     * Whew, now cleanup.  Remember, we are now in the parent directory.
  623. X     */
  624. X    lock = Lock(fib->fib_FileName);
  625. X    parentLock = CurrentDir(lock);
  626. X    UnLock(parentLock);
  627. X    free(fib);
  628. X    return (retval);
  629. X}
  630. X
  631. X/*
  632. X * Lattice C perror() puts out a leading \n - this is the wrong behavior
  633. X */
  634. Xperror(char *s)
  635. X{
  636. X    if ((errno >= 0) && (errno <= sys_nerr))
  637. X    {
  638. X    fputs(s, stderr);
  639. X    fputs(": ", stderr);
  640. X    fputs(sys_errlist[errno], stderr);
  641. X    putc('\n', stderr);
  642. X    fflush(stderr);        /* why do I have to do this???  It shouldn't
  643. X                   be buffered. */
  644. X    }
  645. X    return(errno);
  646. X}
  647. X
  648. X/*
  649. X * It's probably cleaner to write my own mkdir() which takes two arguments,
  650. X * rather than paste in the code to set the mode everywhere mkdir() is
  651. X * called
  652. X */
  653. Xmkdir(char *dirname, int mode)
  654. X{
  655. X    struct FileLock *lock;
  656. X
  657. X    if (lock = CreateDir(dirname))
  658. X    {
  659. X    UnLock(lock);
  660. X    return(SmartSetProtection(dirname, (~(((mode & 0700) >> 5) | 1)) & 0xf));
  661. X    }
  662. X    else
  663. X    {
  664. X    if (IoErr() == ERROR_DIRECTORY_NOT_EMPTY)
  665. X        return(0);
  666. X     errno = EACCES;        /* FIXME */
  667. X    return(-1);
  668. X    }
  669. X}
  670. END_OF_FILE
  671. if test 6424 -ne `wc -c <'amiga.c'`; then
  672.     echo shar: \"'amiga.c'\" unpacked with wrong size!
  673. fi
  674. # end of 'amiga.c'
  675. fi
  676. if test -f 'diffarch.c' -a "${1}" != "-c" ; then 
  677.   echo shar: Will not clobber existing file \"'diffarch.c'\"
  678. else
  679. echo shar: Extracting \"'diffarch.c'\" \(7394 characters\)
  680. sed "s/^X//" >'diffarch.c' <<'END_OF_FILE'
  681. X/*
  682. X * Diff files from a tar archive.
  683. X *
  684. X * Written 30 April 1987 by John Gilmore, ihnp4!hoptoad!gnu.
  685. X *
  686. X * @(#) diffarch.c 1.10 87/11/11 Public Domain - gnu
  687. X */
  688. X
  689. X#include <stdio.h>
  690. X#include <errno.h>
  691. X#include <sys/types.h>
  692. X#include <sys/stat.h>
  693. X
  694. X#ifdef BSD42
  695. X#include <sys/file.h>
  696. X#endif
  697. X
  698. X#ifdef USG
  699. X#include <fcntl.h>
  700. X#endif
  701. X
  702. X/* Some systems don't have these #define's -- we fake it here. */
  703. X#ifndef O_RDONLY
  704. X#define    O_RDONLY    0
  705. X#endif
  706. X#ifndef    O_NDELAY
  707. X#define    O_NDELAY    0
  708. X#endif
  709. X
  710. Xextern int errno;            /* From libc.a */
  711. Xextern char *valloc();            /* From libc.a */
  712. X
  713. X#include "tar.h"
  714. X#include "port.h"
  715. X
  716. Xextern union record *head;        /* Points to current tape header */
  717. Xextern struct stat hstat;        /* Stat struct corresponding */
  718. Xextern int head_standard;        /* Tape header is in ANSI format */
  719. X
  720. Xextern void print_header();
  721. Xextern void skip_file();
  722. X
  723. Xchar *filedata;                /* Pointer to area for reading
  724. X                       file contents into */
  725. X
  726. X/*
  727. X * Initialize for a diff operation
  728. X */
  729. Xdiff_init()
  730. X{
  731. X
  732. X    /*NOSTRICT*/
  733. X    filedata = (char *) valloc((unsigned)blocksize);
  734. X    if (!filedata) {
  735. X        fprintf(stderr,
  736. X        "tar: could not allocate memory for diff buffer of %d bytes\n",
  737. X            blocking);
  738. X        exit(EX_ARGSBAD);
  739. X    }
  740. X}
  741. X
  742. X/*
  743. X * Diff a file against the archive.
  744. X */
  745. Xvoid
  746. Xdiff_archive()
  747. X{
  748. X    register char *data;
  749. X    int fd, check, namelen, written;
  750. X    int err, firsttime;
  751. X    long size;
  752. X    struct stat filestat;
  753. X    char linkbuf[NAMSIZ+3];
  754. X
  755. X    errno = EPIPE;            /* FIXME, remove perrors */
  756. X
  757. X    saverec(&head);            /* Make sure it sticks around */
  758. X    userec(head);            /* And go past it in the archive */
  759. X    decode_header(head, &hstat, &head_standard, 1);    /* Snarf fields */
  760. X
  761. X    /* Print the record from 'head' and 'hstat' */
  762. X    if (f_verbose)
  763. X        print_header(stdout);
  764. X
  765. X    switch (head->header.linkflag) {
  766. X
  767. X    default:
  768. X        annofile(stderr, tar);
  769. X        fprintf(stderr,
  770. X           "Unknown file type '%c' for %s, diffed as normal file\n",
  771. X            head->header.linkflag, head->header.name);
  772. X        /* FALL THRU */
  773. X
  774. X    case LF_OLDNORMAL:
  775. X    case LF_NORMAL:
  776. X    case LF_CONTIG:
  777. X        /*
  778. X         * Appears to be a file.
  779. X         * See if it's really a directory.
  780. X         */
  781. X        namelen = strlen(head->header.name)-1;
  782. X        if (head->header.name[namelen] == '/')
  783. X            goto really_dir;
  784. X
  785. X        fd = open(head->header.name, O_NDELAY|O_RDONLY);
  786. X
  787. X        if (fd < 0) {
  788. X            if (errno == ENOENT) {
  789. X                /* Expected error -- to stdout */
  790. X                annofile(stdout, (char *)NULL);
  791. X                fprintf(stdout, "%s: does not exist\n",
  792. X                    head->header.name);
  793. X            } else {
  794. X                annofile(stderr, (char *)NULL);
  795. X                perror(head->header.name);
  796. X            }
  797. X            skip_file((long)hstat.st_size);
  798. X            goto quit;
  799. X        }
  800. X#ifdef AMIGA
  801. X        err = stat(head->header.name, &filestat);
  802. X#else
  803. X        err = fstat(fd, &filestat);
  804. X#endif
  805. X        if (err < 0) {
  806. X            annofile(stdout, (char *)NULL);
  807. X            fprintf(stdout, "Cannot fstat file ");
  808. X            perror(head->header.name);
  809. X            skip_file((long)hstat.st_size);
  810. X            goto qclose;
  811. X        }
  812. X
  813. X        if ((filestat.st_mode & S_IFMT) != S_IFREG) {
  814. X            annofile(stdout, (char *)NULL);
  815. X            fprintf(stdout, "%s: not a regular file\n",
  816. X                head->header.name);
  817. X            skip_file((long)hstat.st_size);
  818. X            goto qclose;
  819. X        }
  820. X
  821. X        filestat.st_mode &= ~S_IFMT;
  822. X        if (filestat.st_mode != hstat.st_mode)
  823. X            sigh("mode");
  824. X        if (filestat.st_uid  != hstat.st_uid)
  825. X            sigh("uid");
  826. X        if (filestat.st_gid  != hstat.st_gid)
  827. X            sigh("gid");
  828. X        if (filestat.st_size != hstat.st_size) {
  829. X            sigh("size");
  830. X            skip_file((long)hstat.st_size);
  831. X            goto qclose;
  832. X        }
  833. X        if (filestat.st_mtime != hstat.st_mtime)
  834. X            sigh("mod time");
  835. X
  836. X        firsttime = 0;
  837. X
  838. X        for (size = hstat.st_size;
  839. X             size > 0;
  840. X             size -= written) {
  841. X            /*
  842. X             * Locate data, determine max length
  843. X             * writeable, write it, record that
  844. X             * we have used the data, then check
  845. X             * if the write worked.
  846. X             */
  847. X            data = findrec()->charptr;
  848. X            if (data == NULL) {    /* Check it... */
  849. X                annorec(stderr, tar);
  850. X                fprintf(stderr, "Unexpected EOF on archive file\n");
  851. X                break;
  852. X            }
  853. X            written = endofrecs()->charptr - data;
  854. X            if (written > size) written = size;
  855. X            errno = 0;
  856. X            check = read (fd, filedata, written);
  857. X            /*
  858. X             * The following is in violation of strict
  859. X             * typing, since the arg to userec
  860. X             * should be a struct rec *.  FIXME.
  861. X             */
  862. X            userec(data + written - 1);
  863. X            if (check == written) {
  864. X                /* The read worked, now compare the data */
  865. X                if (bcmp(data, filedata, check) == 0)
  866. X                    continue;    /* It compares */
  867. X                if (firsttime++) {
  868. X                    annofile(stdout, (char *)NULL);
  869. X                    fprintf(stdout, "%s: data differs\n",
  870. X                        head->header.name);
  871. X                }
  872. X            }
  873. X
  874. X            /*
  875. X             * Error in reading from file.
  876. X             * Print it, skip to next file in archive.
  877. X             */
  878. X            annofile(stderr, tar);
  879. X            fprintf(stderr,
  880. X    "Tried to read %d bytes from file, could only read %d:\n",
  881. X                written, check);
  882. X            perror(head->header.name);
  883. X            skip_file((long)(size - written));
  884. X            break;    /* Still do the close, mod time, chmod, etc */
  885. X        }
  886. X
  887. X    qclose:
  888. X        check = close(fd);
  889. X        if (check < 0) {
  890. X            annofile(stderr, tar);
  891. X            fprintf(stderr, "Error while closing ");
  892. X            perror(head->header.name);
  893. X        }
  894. X        
  895. X    quit:
  896. X        break;
  897. X
  898. X    case LF_LINK:
  899. X        check = 1;    /* FIXME deal with this */
  900. X        /* check = link (head->header.linkname,
  901. X                  head->header.name); */
  902. X        /* FIXME, don't worry uid, gid, etc... */
  903. X        if (check == 0)
  904. X            break;
  905. X        annofile(stderr, tar);
  906. X        fprintf(stderr, "Could not link %s to ",
  907. X            head->header.name);
  908. X        perror(head->header.linkname);
  909. X        break;
  910. X
  911. X#ifdef S_IFLNK
  912. X    case LF_SYMLINK:
  913. X        check = readlink(head->header.name, linkbuf,
  914. X                 (sizeof linkbuf)-1);
  915. X        
  916. X        if (check < 0) {
  917. X            if (errno == ENOENT) {
  918. X                annofile(stdout, (char *)NULL);
  919. X                fprintf(stdout,
  920. X                    "%s: no such file or directory\n",
  921. X                    head->header.name);
  922. X            } else {
  923. X                annofile(stderr, tar);
  924. X                fprintf(stderr, "Could not read link");
  925. X                perror(head->header.name);
  926. X            }
  927. X            break;
  928. X        }
  929. X
  930. X        linkbuf[check] = '\0';    /* Null-terminate it */
  931. X        if (strncmp(head->header.linkname, linkbuf, check) != 0) {
  932. X            annofile(stdout, (char *)NULL);
  933. X            fprintf(stdout, "%s: symlink differs\n",
  934. X                head->header.linkname);
  935. X        }
  936. X        break;
  937. X#endif
  938. X
  939. X    case LF_CHR:
  940. X        hstat.st_mode |= S_IFCHR;
  941. X        goto make_node;
  942. X
  943. X#ifdef S_IFBLK
  944. X    /* If local system doesn't support block devices, use default case */
  945. X    case LF_BLK:
  946. X        hstat.st_mode |= S_IFBLK;
  947. X        goto make_node;
  948. X#endif
  949. X
  950. X#ifdef S_IFIFO
  951. X    /* If local system doesn't support FIFOs, use default case */
  952. X    case LF_FIFO:
  953. X        hstat.st_mode |= S_IFIFO;
  954. X        hstat.st_rdev = 0;        /* FIXME, do we need this? */
  955. X        goto make_node;
  956. X#endif
  957. X
  958. X    make_node:
  959. X        /* FIXME, deal with umask */
  960. X        
  961. X        check = 1; /* FIXME, implement this */
  962. X        /* check = mknod(head->header.name, (int) hstat.st_mode,
  963. X            (int) hstat.st_rdev); */
  964. X        if (check != 0) {
  965. X            annofile(stderr, tar);
  966. X            fprintf(stderr, "Could not make ");
  967. X            perror(head->header.name);
  968. X            break;
  969. X        };
  970. X        break;
  971. X
  972. X    case LF_DIR:
  973. X        /* Check for trailing / */
  974. X        namelen = strlen(head->header.name)-1;
  975. X    really_dir:
  976. X        while (namelen && head->header.name[namelen] == '/')
  977. X            head->header.name[namelen--] = '\0';    /* Zap / */
  978. X        
  979. X        check = 1; /* FIXME, implement this */
  980. X        /* check = mkdir(head->header.name, 0300 | (int)hstat.st_mode); */
  981. X#ifndef AMIGA
  982. X        if (check != 0) {
  983. X            annofile(stderr, tar);
  984. X            fprintf(stderr, "Could not make directory ");
  985. X            perror(head->header.name);
  986. X            break;
  987. X        }
  988. X#endif        
  989. X        break;
  990. X
  991. X    }
  992. X
  993. X    /* We don't need to save it any longer. */
  994. X    saverec((union record **) 0);    /* Unsave it */
  995. X}
  996. X
  997. X/*
  998. X * Sigh about something that differs.
  999. X */
  1000. Xsigh(what)
  1001. X    char *what;
  1002. X{
  1003. X
  1004. X    annofile(stdout, (char *)NULL);
  1005. X    fprintf(stdout, "%s: %s differs\n",
  1006. X        head->header.name, what);
  1007. X}
  1008. END_OF_FILE
  1009. if test 7394 -ne `wc -c <'diffarch.c'`; then
  1010.     echo shar: \"'diffarch.c'\" unpacked with wrong size!
  1011. fi
  1012. # end of 'diffarch.c'
  1013. fi
  1014. if test -f 'dir.c' -a "${1}" != "-c" ; then 
  1015.   echo shar: Will not clobber existing file \"'dir.c'\"
  1016. else
  1017. echo shar: Extracting \"'dir.c'\" \(1611 characters\)
  1018. sed "s/^X//" >'dir.c' <<'END_OF_FILE'
  1019. X#include <dirent.h>
  1020. X
  1021. XDIR *
  1022. Xopendir(char *dirname)
  1023. X{
  1024. X    struct FileLock *alock;
  1025. X    struct FileInfoBlock *fib;
  1026. X    DIR *dp;
  1027. X
  1028. X    if (alock = Lock(dirname, ACCESS_READ))
  1029. X    {
  1030. X    if ((fib = (struct FileInfoBlock *) malloc(sizeof(*fib))) == NULL)
  1031. X    {
  1032. X        UnLock(alock);
  1033. X        return(NULL);    /* malloc failed */
  1034. X    }
  1035. X    if (Examine(alock, fib) && (fib->fib_DirEntryType > 0))
  1036. X    {
  1037. X        if (dp = (DIR *) malloc(sizeof(*dp)))
  1038. X        {
  1039. X            if ((dp->dd_dirent =
  1040. X            (struct dirent *) malloc(DIRENTSIZ(MAXNAMELEN))) == NULL)
  1041. X        {
  1042. X                UnLock(alock);
  1043. X            free(fib);
  1044. X            free(dp);
  1045. X            return(NULL);    /* malloc failed */
  1046. X            }
  1047. X        dp->dd_lock = alock;
  1048. X        dp->dd_fib = fib;
  1049. X            dp->dd_loc = 0;
  1050. X            return(dp);
  1051. X            }
  1052. X        else
  1053. X        {
  1054. X            UnLock(alock);
  1055. X        free(fib);
  1056. X            return(NULL);        /* malloc failed */
  1057. X        }
  1058. X    }
  1059. X    else
  1060. X    {
  1061. X        UnLock(alock);
  1062. X        free(fib);
  1063. X        return(NULL);        /* not a directory */
  1064. X    }
  1065. X    }
  1066. X    else
  1067. X    return(NULL);            /* couldn't access file */
  1068. X}
  1069. X
  1070. X
  1071. Xstruct dirent *
  1072. Xreaddir(DIR *dirp)
  1073. X{
  1074. X    struct dirent *dp;
  1075. X
  1076. X    if ((dirp == NULL) || (dirp->dd_dirent == NULL))
  1077. X    return(NULL);            /* malloc failed */
  1078. X    if (ExNext(dirp->dd_lock, dirp->dd_fib))
  1079. X    {
  1080. X    dirp->dd_loc++;
  1081. X    dp = dirp->dd_dirent;
  1082. X    dp->d_ino = 0;
  1083. X    dp->d_reclen = strlen(dirp->dd_fib->fib_FileName);
  1084. X    strcpy(dp->d_name, dirp->dd_fib->fib_FileName);
  1085. X        return(dirp->dd_dirent);
  1086. X    }
  1087. X    else
  1088. X    return(NULL);            /* hit end */
  1089. X}
  1090. X
  1091. Xint
  1092. Xclosedir(DIR *dirp)
  1093. X{
  1094. X    if ((dirp == NULL) || (dirp->dd_dirent == NULL))
  1095. X    return(1);
  1096. X    UnLock(dirp->dd_lock);
  1097. X    free(dirp->dd_dirent);
  1098. X    free(dirp->dd_fib);
  1099. X    free(dirp);
  1100. X    return(0);
  1101. X}
  1102. END_OF_FILE
  1103. if test 1611 -ne `wc -c <'dir.c'`; then
  1104.     echo shar: \"'dir.c'\" unpacked with wrong size!
  1105. fi
  1106. # end of 'dir.c'
  1107. fi
  1108. if test -f 'dirent.h' -a "${1}" != "-c" ; then 
  1109.   echo shar: Will not clobber existing file \"'dirent.h'\"
  1110. else
  1111. echo shar: Extracting \"'dirent.h'\" \(899 characters\)
  1112. sed "s/^X//" >'dirent.h' <<'END_OF_FILE'
  1113. X/*
  1114. X * dirent.h for AmigaDOS - derived from an old document written by Doug Gwyn
  1115. X *
  1116. X * $Header$
  1117. X */
  1118. X#include <sys/types.h>
  1119. X#include <libraries/dosextens.h>
  1120. X#include <proto/dos.h>
  1121. X
  1122. X#define MAXNAMELEN    108        /* space in FIB for name */
  1123. X
  1124. X#ifndef NAME_MAX
  1125. X#define NAME_MAX    (MAXNAMELEN - 1)
  1126. X#endif
  1127. X
  1128. Xstruct dirent  {
  1129. X    long        d_ino;
  1130. X    off_t        d_off;
  1131. X    unsigned short    d_reclen;
  1132. X    char        d_name[1];
  1133. X};
  1134. X
  1135. Xtypedef struct  {
  1136. X    struct dirent    *dd_dirent;    /* ok to reuse this over and over */
  1137. X    struct FileLock    *dd_lock;
  1138. X    struct FileInfoBlock    *dd_fib;
  1139. X    int        dd_loc;
  1140. X} DIR;
  1141. X
  1142. X#define DIRENTBASESIZ    (&((struct dirent *) 0)->d_name \
  1143. X            - (char *) &((struct dirent *) 0)->d_ino)
  1144. X#define    DIRENTSIZ(namelen)    ((DIRENTBASESIZ + sizeof(long) + (namelen)) \
  1145. X                / sizeof(long) * 4)
  1146. X
  1147. XDIR    *opendir(char *dirname);
  1148. Xstruct dirent    *readdir(DIR *dirp);
  1149. Xoff_t    telldir(DIR *dirp);
  1150. Xvoid    seekdir(DIR *dirp, off_t loc);
  1151. Xvoid    rewinddir(DIR *dirp);
  1152. END_OF_FILE
  1153. if test 899 -ne `wc -c <'dirent.h'`; then
  1154.     echo shar: \"'dirent.h'\" unpacked with wrong size!
  1155. fi
  1156. # end of 'dirent.h'
  1157. fi
  1158. if test -f 'getoldopt.c' -a "${1}" != "-c" ; then 
  1159.   echo shar: Will not clobber existing file \"'getoldopt.c'\"
  1160. else
  1161. echo shar: Extracting \"'getoldopt.c'\" \(1374 characters\)
  1162. sed "s/^X//" >'getoldopt.c' <<'END_OF_FILE'
  1163. X/*
  1164. X * Plug-compatible replacement for getopt() for parsing tar-like
  1165. X * arguments.  If the first argument begins with "-", it uses getopt;
  1166. X * otherwise, it uses the old rules used by tar, dump, and ps.
  1167. X *
  1168. X * Written 25 August 1985 by John Gilmore (ihnp4!hoptoad!gnu) and placed
  1169. X * in the Pubic Domain for your edification and enjoyment.
  1170. X *
  1171. X * @(#)getoldopt.c 1.4 2/4/86 Public Domain - gnu
  1172. X */
  1173. X
  1174. X#include <stdio.h>
  1175. X
  1176. X
  1177. Xint
  1178. Xgetoldopt(argc, argv, optstring)
  1179. X    int    argc;
  1180. X    char    **argv;
  1181. X    char    *optstring;
  1182. X{
  1183. X    extern char    *optarg;    /* Points to next arg */
  1184. X    extern int    optind;        /* Global argv index */
  1185. X    static char    *key;        /* Points to next keyletter */
  1186. X    static char    use_getopt;    /* !=0 if argv[1][0] was '-' */
  1187. X    extern char    *index();
  1188. X    char        c;
  1189. X    char        *place;
  1190. X
  1191. X    optarg = NULL;
  1192. X    
  1193. X    if (key == NULL) {        /* First time */
  1194. X        if (argc < 2) return EOF;
  1195. X        key = argv[1];
  1196. X        if (*key == '-')
  1197. X            use_getopt++;
  1198. X        else
  1199. X            optind = 2;
  1200. X    }
  1201. X
  1202. X    if (use_getopt)
  1203. X        return getopt(argc, argv, optstring);
  1204. X
  1205. X    c = *key++;
  1206. X    if (c == '\0') {
  1207. X        key--;
  1208. X        return EOF;
  1209. X    }
  1210. X    place = index(optstring, c);
  1211. X
  1212. X    if (place == NULL || c == ':') {
  1213. X        fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
  1214. X        return('?');
  1215. X    }
  1216. X
  1217. X    place++;
  1218. X    if (*place == ':') {
  1219. X        if (optind < argc) {
  1220. X            optarg = argv[optind];
  1221. X            optind++;
  1222. X        } else {
  1223. X            fprintf(stderr, "%s: %c argument missing\n",
  1224. X                argv[0], c);
  1225. X            return('?');
  1226. X        }
  1227. X    }
  1228. X
  1229. X    return(c);
  1230. X}
  1231. END_OF_FILE
  1232. if test 1374 -ne `wc -c <'getoldopt.c'`; then
  1233.     echo shar: \"'getoldopt.c'\" unpacked with wrong size!
  1234. fi
  1235. # end of 'getoldopt.c'
  1236. fi
  1237. if test -f 'getopt.c' -a "${1}" != "-c" ; then 
  1238.   echo shar: Will not clobber existing file \"'getopt.c'\"
  1239. else
  1240. echo shar: Extracting \"'getopt.c'\" \(1489 characters\)
  1241. sed "s/^X//" >'getopt.c' <<'END_OF_FILE'
  1242. X#include <stdio.h>
  1243. X
  1244. X/*
  1245. X * get option letter from argument vector
  1246. X */
  1247. Xint    opterr = 1;        /* useless, never set or used */
  1248. Xint    optind = 1;        /* index into parent argv vector */
  1249. Xint    optopt;            /* character checked for validity */
  1250. Xchar    *optarg;        /* argument associated with option */
  1251. X
  1252. X#define BADCH    (int)'?'
  1253. X#define EMSG    ""
  1254. X#define tell(s)    fputs(*nargv,stderr);fputs(s,stderr); \
  1255. X        fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
  1256. X
  1257. Xgetopt(nargc,nargv,ostr)
  1258. Xint    nargc;
  1259. Xchar    **nargv,
  1260. X    *ostr;
  1261. X{
  1262. X    static char    *place = EMSG;    /* option letter processing */
  1263. X    register char    *oli;        /* option letter list index */
  1264. X    char    *index();
  1265. X
  1266. X/*    fprintf(stderr, "getopt(): optind=%d optarg=0x%x\n", optind, optarg); */
  1267. X    if(!*place) {            /* update scanning pointer */
  1268. X        if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
  1269. X        if (*place == '-') {    /* found "--" */
  1270. X            ++optind;
  1271. X            return(EOF);
  1272. X        }
  1273. X    }                /* option letter okay? */
  1274. X    if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) {
  1275. X        if(!*place) ++optind;
  1276. X        tell(": illegal option -- ");
  1277. X    }
  1278. X    if (*++oli != ':') {        /* don't need argument */
  1279. X        optarg = NULL;
  1280. X        if (!*place) ++optind;
  1281. X    }
  1282. X    else {                /* need an argument */
  1283. X        if (*place) optarg = place;    /* no white space */
  1284. X        else if (nargc <= ++optind) {    /* no arg */
  1285. X            place = EMSG;
  1286. X            tell(": option requires an argument -- ");
  1287. X        }
  1288. X         else optarg = nargv[optind];    /* white space */
  1289. X        place = EMSG;
  1290. X        ++optind;
  1291. X    }
  1292. X    return(optopt);            /* dump back option letter */
  1293. X}
  1294. X
  1295. END_OF_FILE
  1296. if test 1489 -ne `wc -c <'getopt.c'`; then
  1297.     echo shar: \"'getopt.c'\" unpacked with wrong size!
  1298. fi
  1299. # end of 'getopt.c'
  1300. fi
  1301. if test -f 'open3.h' -a "${1}" != "-c" ; then 
  1302.   echo shar: Will not clobber existing file \"'open3.h'\"
  1303. else
  1304. echo shar: Extracting \"'open3.h'\" \(1906 characters\)
  1305. sed "s/^X//" >'open3.h' <<'END_OF_FILE'
  1306. X/*
  1307. X * @(#)open3.h 1.4 87/11/11    Public Domain.
  1308. X *
  1309. X * open3.h -- #defines for the various flags for the Sys V style 3-argument
  1310. X * open() call.  On BSD or System 5, the system already has this in an
  1311. X * include file.  This file is needed for V7 and MINIX systems for the
  1312. X * benefit of open3() in port.c, a routine that emulates the 3-argument
  1313. X * call using system calls available on V7/MINIX. 
  1314. X *
  1315. X * This file is needed by PD tar even if we aren't using the
  1316. X * emulator, since the #defines for O_WRONLY, etc. are used in
  1317. X * a couple of places besides the open() calls, (e.g. in the assignment
  1318. X * to openflag in extract.c).  We just #include this rather than
  1319. X * #ifdef them out.
  1320. X *
  1321. X * Written 6/10/87 by rmtodd@uokmax (Richard Todd).
  1322. X *
  1323. X * The names have been changed by John Gilmore, 31 July 1987, since
  1324. X * Richard called it "bsdopen", and really this change was introduced in
  1325. X * AT&T Unix systems before BSD picked it up.
  1326. X */
  1327. X
  1328. X/* Only one of the next three should be specified */
  1329. X#define O_RDONLY     0 /* only allow read */
  1330. X#define    O_WRONLY     1 /* only allow write */
  1331. X#define    O_RDWR         2 /* both are allowed */
  1332. X
  1333. X/* The rest of these can be OR-ed in to the above. */
  1334. X/*
  1335. X * O_NDELAY isn't implemented by the emulator.  It's only useful (to tar) on
  1336. X * systems that have named pipes anyway; it prevents tar's hanging by
  1337. X * opening a named pipe.  We #ifndef it because some systems already have
  1338. X * it defined.
  1339. X */
  1340. X#ifndef O_NDELAY
  1341. X#define O_NDELAY     4 /* don't block on opening devices that would
  1342. X                * block on open -- ignored by emulator. */
  1343. X#endif
  1344. X#define O_CREAT         8 /* create file if needed */
  1345. X#define O_EXCL        16 /* file cannot already exist */
  1346. X#define O_TRUNC        32 /* truncate file on open */
  1347. X#define O_APPEND    64 /* always write at end of file -- ignored by emul */
  1348. X
  1349. X#ifdef EMUL_OPEN3
  1350. X/*
  1351. X * make emulation transparent to rest of file -- redirect all open() calls
  1352. X * to our routine
  1353. X */
  1354. X#define open    open3
  1355. X#endif
  1356. END_OF_FILE
  1357. if test 1906 -ne `wc -c <'open3.h'`; then
  1358.     echo shar: \"'open3.h'\" unpacked with wrong size!
  1359. fi
  1360. # end of 'open3.h'
  1361. fi
  1362. if test -f 'port.h' -a "${1}" != "-c" ; then 
  1363.   echo shar: Will not clobber existing file \"'port.h'\"
  1364. else
  1365. echo shar: Extracting \"'port.h'\" \(929 characters\)
  1366. sed "s/^X//" >'port.h' <<'END_OF_FILE'
  1367. X/*
  1368. X * Portability declarations for public domain tar.
  1369. X *
  1370. X * @(#)port.h 1.3    87/11/11    Public Domain by John Gilmore, 1986
  1371. X */
  1372. X
  1373. X/*
  1374. X * Everybody does wait() differently.  There seem to be no definitions
  1375. X * for this in V7 (e.g. you are supposed to shift and mask things out
  1376. X * using constant shifts and masks.)  So fuck 'em all -- my own non
  1377. X * standard but portable macros.  Don't change to a "union wait"
  1378. X * based approach -- the ordering of the elements of the struct 
  1379. X * depends on the byte-sex of the machine.  Foo!
  1380. X */
  1381. X#define    TERM_SIGNAL(status)    ((status) & 0x7F)
  1382. X#define TERM_COREDUMP(status)    (((status) & 0x80) != 0)
  1383. X#define TERM_VALUE(status)    ((status) >> 8)
  1384. X
  1385. X#if defined(MSDOS) || defined(AMIGA)
  1386. X/* missing things from sys/stat.h */
  1387. X#define    S_ISUID        0
  1388. X#define    S_ISGID        0
  1389. X#define    S_ISVTX        0
  1390. X
  1391. X/* device stuff */
  1392. X#define    makedev(ma, mi)        ((ma << 8) | mi)
  1393. X#define    major(dev)        (dev)
  1394. X#define    minor(dev)        (dev)
  1395. X#endif    /* MSDOS */
  1396. END_OF_FILE
  1397. if test 929 -ne `wc -c <'port.h'`; then
  1398.     echo shar: \"'port.h'\" unpacked with wrong size!
  1399. fi
  1400. # end of 'port.h'
  1401. fi
  1402. if test -f 'stat.h' -a "${1}" != "-c" ; then 
  1403.   echo shar: Will not clobber existing file \"'stat.h'\"
  1404. else
  1405. echo shar: Extracting \"'stat.h'\" \(426 characters\)
  1406. sed "s/^X//" >'stat.h' <<'END_OF_FILE'
  1407. X#include <libraries/dos.h>
  1408. X
  1409. Xstruct stat  {
  1410. X    int    st_mode;
  1411. X    int    st_dev;
  1412. X    int    st_ino;
  1413. X    int    st_size;
  1414. X    int    st_rdev;
  1415. X    int    st_gid;
  1416. X    int    st_uid;
  1417. X    int    st_mtime;
  1418. X    int    st_nlink;
  1419. X/*
  1420. X * These last fields are specific to the Amiga
  1421. X */
  1422. X    struct  DateStamp st_date;
  1423. X    u_long    st_prot;
  1424. X    char    st_comment[80];      /* header files says last 36 bytes unused */
  1425. X};
  1426. X
  1427. X#define S_IFREG    01000
  1428. X#define S_IFDIR    02000
  1429. X#define S_IFCHR 04000
  1430. X#define    S_IFMT    07000
  1431. END_OF_FILE
  1432. if test 426 -ne `wc -c <'stat.h'`; then
  1433.     echo shar: \"'stat.h'\" unpacked with wrong size!
  1434. fi
  1435. # end of 'stat.h'
  1436. fi
  1437. if test -f 'tar.h' -a "${1}" != "-c" ; then 
  1438.   echo shar: Will not clobber existing file \"'tar.h'\"
  1439. else
  1440. echo shar: Extracting \"'tar.h'\" \(5813 characters\)
  1441. sed "s/^X//" >'tar.h' <<'END_OF_FILE'
  1442. X/*
  1443. X * Header file for public domain tar (tape archive) program.
  1444. X *
  1445. X * @(#)tar.h 1.24 87/11/06    Public Domain.
  1446. X *
  1447. X * Created 25 August 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  1448. X */
  1449. X
  1450. X/*
  1451. X * Kludge for handling systems that can't cope with multiple
  1452. X * external definitions of a variable.  In ONE routine (tar.c),
  1453. X * we #define TAR_EXTERN to null; here, we set it to "extern" if
  1454. X * it is not already set.
  1455. X */
  1456. X#ifndef TAR_EXTERN
  1457. X#define TAR_EXTERN extern
  1458. X#endif
  1459. X
  1460. X/*
  1461. X * Header block on tape.
  1462. X *
  1463. X * I'm going to use traditional DP naming conventions here.
  1464. X * A "block" is a big chunk of stuff that we do I/O on.
  1465. X * A "record" is a piece of info that we care about.
  1466. X * Typically many "record"s fit into a "block".
  1467. X */
  1468. X#define    RECORDSIZE    512
  1469. X#define    NAMSIZ    100
  1470. X#define    TUNMLEN    32
  1471. X#define    TGNMLEN    32
  1472. X
  1473. Xunion record {
  1474. X    char        charptr[RECORDSIZE];
  1475. X    struct header {
  1476. X        char    name[NAMSIZ];
  1477. X        char    mode[8];
  1478. X        char    uid[8];
  1479. X        char    gid[8];
  1480. X        char    size[12];
  1481. X        char    mtime[12];
  1482. X        char    chksum[8];
  1483. X        char    linkflag;
  1484. X        char    linkname[NAMSIZ];
  1485. X        char    magic[8];
  1486. X        char    uname[TUNMLEN];
  1487. X        char    gname[TGNMLEN];
  1488. X        char    devmajor[8];
  1489. X        char    devminor[8];
  1490. X#ifdef AMIGA
  1491. X        char    magic_cookie[9];    /* "AmigaTar" */
  1492. X        char    amiga_modes[9];        /* Protection, hex ascii */
  1493. X        char    comment[80];        /* Comment */
  1494. X        char    ds_Days[9];        /* Date Stamp, hex ascii */
  1495. X        char    ds_Minute[9];        /* Date Stamp, hex ascii */
  1496. X        char    ds_Tick[9];        /* Date Stamp, hex ascii */
  1497. X#endif
  1498. X    } header;
  1499. X};
  1500. X
  1501. X/* The checksum field is filled with this while the checksum is computed. */
  1502. X#define    CHKBLANKS    "        "    /* 8 blanks, no null */
  1503. X
  1504. X/* The magic field is filled with this if uname and gname are valid. */
  1505. X#define    TMAGIC        "ustar  "    /* 7 chars and a null */
  1506. X
  1507. X/* The linkflag defines the type of file */
  1508. X#define    LF_OLDNORMAL    '\0'        /* Normal disk file, Unix compat */
  1509. X#define    LF_NORMAL    '0'        /* Normal disk file */
  1510. X#define    LF_LINK        '1'        /* Link to previously dumped file */
  1511. X#define    LF_SYMLINK    '2'        /* Symbolic link */
  1512. X#define    LF_CHR        '3'        /* Character special file */
  1513. X#define    LF_BLK        '4'        /* Block special file */
  1514. X#define    LF_DIR        '5'        /* Directory */
  1515. X#define    LF_FIFO        '6'        /* FIFO special file */
  1516. X#define    LF_CONTIG    '7'        /* Contiguous file */
  1517. X/* Further link types may be defined later. */
  1518. X
  1519. X/*
  1520. X * Exit codes from the "tar" program
  1521. X */
  1522. X#define    EX_SUCCESS    0        /* success! */
  1523. X#define    EX_ARGSBAD    1        /* invalid args */
  1524. X#define    EX_BADFILE    2        /* invalid filename */
  1525. X#define    EX_BADARCH    3        /* bad archive */
  1526. X#define    EX_SYSTEM    4        /* system gave unexpected error */
  1527. X
  1528. X
  1529. X/*
  1530. X * Global variables
  1531. X */
  1532. XTAR_EXTERN union record    *ar_block;    /* Start of block of archive */
  1533. XTAR_EXTERN union record    *ar_record;    /* Current record of archive */
  1534. XTAR_EXTERN union record    *ar_last;    /* Last+1 record of archive block */
  1535. XTAR_EXTERN char        ar_reading;    /* 0 writing, !0 reading archive */
  1536. XTAR_EXTERN int        blocking;    /* Size of each block, in records */
  1537. XTAR_EXTERN int        blocksize;    /* Size of each block, in bytes */
  1538. XTAR_EXTERN char        *ar_file;    /* File containing archive */
  1539. XTAR_EXTERN char        *name_file;    /* File containing names to work on */
  1540. XTAR_EXTERN char        *tar;        /* Name of this program */
  1541. X
  1542. X/*
  1543. X * Flags from the command line
  1544. X */
  1545. X#ifdef AMIGA
  1546. XTAR_EXTERN char f_archive_set;        /* -a */
  1547. XTAR_EXTERN char f_archive_check;    /* -A */
  1548. X#endif
  1549. XTAR_EXTERN char    f_reblock;        /* -B */
  1550. XTAR_EXTERN char    f_create;        /* -c */
  1551. XTAR_EXTERN char    f_diff;            /* -d */
  1552. XTAR_EXTERN char    f_dironly;        /* -D */
  1553. XTAR_EXTERN char    f_follow_links;        /* -h */
  1554. XTAR_EXTERN char    f_ignorez;        /* -i */
  1555. XTAR_EXTERN char    f_keep;            /* -k */
  1556. XTAR_EXTERN char f_local_filesys;    /* -l */
  1557. XTAR_EXTERN char    f_modified;        /* -m */
  1558. XTAR_EXTERN char    f_oldarch;        /* -o */
  1559. XTAR_EXTERN char    f_use_protection;    /* -p */
  1560. XTAR_EXTERN char    f_sayblock;        /* -R */
  1561. XTAR_EXTERN char    f_sorted_names;        /* -s */
  1562. XTAR_EXTERN char    f_list;            /* -t */
  1563. XTAR_EXTERN char    f_namefile;        /* -T */
  1564. XTAR_EXTERN char    f_verbose;        /* -v */
  1565. XTAR_EXTERN char    f_extract;        /* -x */
  1566. XTAR_EXTERN char    f_compress;        /* -z */
  1567. X
  1568. X/*
  1569. X * We now default to Unix Standard format rather than 4.2BSD tar format.
  1570. X * The code can actually produce all three:
  1571. X *    f_standard    ANSI standard
  1572. X *    f_oldarch    V7
  1573. X *    neither        4.2BSD
  1574. X * but we don't bother, since 4.2BSD can read ANSI standard format anyway.
  1575. X * The only advantage to the "neither" option is that we can cmp(1) our
  1576. X * output to the output of 4.2BSD tar, for debugging.
  1577. X */
  1578. X#define        f_standard        (!f_oldarch)
  1579. X
  1580. X/*
  1581. X * Structure for keeping track of filenames and lists thereof.
  1582. X */
  1583. Xstruct name {
  1584. X    struct name    *next;
  1585. X    short        length;        /* cached strlen(name) */
  1586. X    char        found;        /* A matching file has been found */
  1587. X    char        firstch;    /* First char is literally matched */
  1588. X    char        regexp;        /* This name is a regexp, not literal */
  1589. X    char        name[NAMSIZ+1];
  1590. X};
  1591. X
  1592. XTAR_EXTERN struct name    *namelist;    /* Points to first name in list */
  1593. XTAR_EXTERN struct name    *namelast;    /* Points to last name in list */
  1594. X
  1595. XTAR_EXTERN int        archive;    /* File descriptor for archive file */
  1596. XTAR_EXTERN int        errors;        /* # of files in error */
  1597. X
  1598. X/*
  1599. X *
  1600. X * Due to the next struct declaration, each routine that includes
  1601. X * "tar.h" must also include <sys/types.h>.  I tried to make it automatic,
  1602. X * but System V has no defines in <sys/types.h>, so there is no way of
  1603. X * knowing when it has been included.  In addition, it cannot be included
  1604. X * twice, but must be included exactly once.  Argghh!
  1605. X *
  1606. X * Thanks, typedef.  Thanks, USG.
  1607. X */
  1608. Xstruct link {
  1609. X    struct link    *next;
  1610. X    dev_t        dev;
  1611. X    ino_t        ino;
  1612. X    short        linkcount;
  1613. X    char        name[NAMSIZ+1];
  1614. X};
  1615. X
  1616. XTAR_EXTERN struct link    *linklist;    /* Points to first link in list */
  1617. X
  1618. X
  1619. X/*
  1620. X * Error recovery stuff
  1621. X */
  1622. XTAR_EXTERN char        read_error_flag;
  1623. X
  1624. X
  1625. X/*
  1626. X * Declarations of functions available to the world.
  1627. X */
  1628. Xunion record *findrec();
  1629. Xvoid userec();
  1630. Xunion record *endofrecs();
  1631. Xvoid anno();
  1632. X#define     annorec(stream, msg)    anno(stream, msg, 0)    /* Cur rec */
  1633. X#define    annofile(stream, msg)    anno(stream, msg, 1)    /* Saved rec */
  1634. END_OF_FILE
  1635. if test 5813 -ne `wc -c <'tar.h'`; then
  1636.     echo shar: \"'tar.h'\" unpacked with wrong size!
  1637. fi
  1638. # end of 'tar.h'
  1639. fi
  1640. if test -f 'tar.lnk' -a "${1}" != "-c" ; then 
  1641.   echo shar: Will not clobber existing file \"'tar.lnk'\"
  1642. else
  1643. echo shar: Extracting \"'tar.lnk'\" \(198 characters\)
  1644. sed "s/^X//" >'tar.lnk' <<'END_OF_FILE'
  1645. XFROM LIB:c.o+"tar.o"+"buffer.o"+"create.o"+"diffarch.o"+"extract.o"+"getoldopt.o"+"getopt.o"+"list.o"+"port.o"+"wildmat.o"+
  1646. X"utime.o"+"/dirlib/dir.o"+"amiga.o"
  1647. XTO "tar"
  1648. XLIB LIB:lc.lib LIB:amiga.lib
  1649. END_OF_FILE
  1650. if test 198 -ne `wc -c <'tar.lnk'`; then
  1651.     echo shar: \"'tar.lnk'\" unpacked with wrong size!
  1652. fi
  1653. # end of 'tar.lnk'
  1654. fi
  1655. if test -f 'types.h' -a "${1}" != "-c" ; then 
  1656.   echo shar: Will not clobber existing file \"'types.h'\"
  1657. else
  1658. echo shar: Extracting \"'types.h'\" \(210 characters\)
  1659. sed "s/^X//" >'types.h' <<'END_OF_FILE'
  1660. Xtypedef unsigned long    u_long;
  1661. Xtypedef unsigned int    u_int;
  1662. Xtypedef unsigned short    u_short;
  1663. Xtypedef unsigned char    u_char;
  1664. Xtypedef int        dev_t;
  1665. Xtypedef int        ino_t;
  1666. Xtypedef    unsigned short    off_t;
  1667. Xtypedef int        time_t;
  1668. END_OF_FILE
  1669. if test 210 -ne `wc -c <'types.h'`; then
  1670.     echo shar: \"'types.h'\" unpacked with wrong size!
  1671. fi
  1672. # end of 'types.h'
  1673. fi
  1674. if test -f 'utime.c' -a "${1}" != "-c" ; then 
  1675.   echo shar: Will not clobber existing file \"'utime.c'\"
  1676. else
  1677. echo shar: Extracting \"'utime.c'\" \(4532 characters\)
  1678. sed "s/^X//" >'utime.c' <<'END_OF_FILE'
  1679. X/*
  1680. X * TITLE: touch.c This is a simple command to set the date of a file to
  1681. X * now. It was compiled using Greenhills C.  You might have to change it a
  1682. X * little for use with Lattice or Manx. The program compiles with just
  1683. X * amigalib.  (that's why those string functions are tacked on the end of
  1684. X * the file)
  1685. X */
  1686. X
  1687. X/*
  1688. X * Changed to be utime function by Jonathan Hue
  1689. X */
  1690. X
  1691. X/* touch.c by Phil Lindsay and Andy Finkel              */
  1692. X/* (c) 1986 Commodore-Amiga, Inc.                       */
  1693. X/* Permission to use in any way granted, as long as     */
  1694. X/* the copyright notice stays intact                    */
  1695. X
  1696. X#include "exec/types.h"
  1697. X#include "exec/ports.h"
  1698. X#include "exec/io.h"
  1699. X#include "exec/memory.h"
  1700. X#include "libraries/dos.h"
  1701. X#include "libraries/dosextens.h"
  1702. X#include <sys/types.h>
  1703. X#include <errno.h>
  1704. X
  1705. Xextern LONG sendpkt();
  1706. X
  1707. X#define ACTION_SET_DATE     34
  1708. X
  1709. Xstatic struct DateStamp *seconds2AmiTime();
  1710. X
  1711. Xint
  1712. Xutime(char *filename, time_t unixtime[2])
  1713. X{
  1714. X    struct DateStamp dateStamp;
  1715. X
  1716. X    return(utime_from_stamp(filename, seconds2AmiTime(unixtime[1]),
  1717. X                &dateStamp));
  1718. X}
  1719. X
  1720. Xint
  1721. Xutime_from_stamp(char *filename, struct DateStamp *ds)
  1722. X{
  1723. X    struct MsgPort *task;
  1724. X    struct FileInfoBlock *fib;
  1725. X    LONG arg[4];
  1726. X    LONG rc;
  1727. X    ULONG lock;
  1728. X    ULONG plock;
  1729. X    UBYTE *pointer;
  1730. X
  1731. X    pointer = NULL;
  1732. X    if (!(pointer = (UBYTE *) AllocMem(64, MEMF_PUBLIC)))
  1733. X    {
  1734. X    errno = ENOMEM;
  1735. X    return(-1);
  1736. X    }
  1737. X    if (!(task = (struct MsgPort *) DeviceProc(filename)))
  1738. X    {
  1739. X    FreeMem(pointer, 64);
  1740. X    errno = ENOENT;
  1741. X    return(-1);
  1742. X    }
  1743. X    if (!(lock = (ULONG) Lock(filename, SHARED_LOCK)))
  1744. X    {
  1745. X    FreeMem(pointer, 64);
  1746. X    errno = ENOENT;
  1747. X    return(-1);
  1748. X    }
  1749. X    plock = (ULONG) ParentDir(lock);
  1750. X    if (!plock)            /* filename is root dir, can't set time */
  1751. X    {
  1752. X    FreeMem(pointer, 64);    /* sometimes you almost want to use a goto */
  1753. X    errno = EACCES;
  1754. X    UnLock(lock);
  1755. X    return(-1);
  1756. X    }
  1757. X    if (!(fib = malloc(sizeof(*fib))))
  1758. X    {
  1759. X    FreeMem(pointer, 64);
  1760. X    errno = ENOMEM;
  1761. X    UnLock(lock);
  1762. X    return(-1);
  1763. X    }
  1764. X    Examine(lock, fib);
  1765. X    UnLock(lock);
  1766. X    strcpy((pointer + 1), fib->fib_FileName);
  1767. X    *pointer = strlen(fib->fib_FileName);
  1768. X    free(fib);
  1769. X    arg[0] = NULL;
  1770. X    arg[1] = plock;
  1771. X    arg[2] = (ULONG) & pointer[0] >> 2;    /* BSTR of filename */
  1772. X    arg[3] = (ULONG) ds;        /* DateStamp */
  1773. X    rc = sendpkt(task, ACTION_SET_DATE, arg, 4);
  1774. X
  1775. X    UnLock(plock);
  1776. X    FreeMem(pointer, 64);
  1777. X    return (0);
  1778. X}
  1779. X
  1780. X
  1781. XLONG
  1782. Xsendpkt(id, type, args, nargs)
  1783. Xstruct MsgPort *id;/* process indentifier ... (handlers message port ) */
  1784. XLONG type;       /* packet type ... (what you want handler to do )   */
  1785. XLONG args[];            /* a pointer to a argument list */
  1786. XLONG nargs;                /* number of arguments in list  */
  1787. X{
  1788. X
  1789. X    struct MsgPort *replyport;
  1790. X    struct StandardPacket *packet = NULL;
  1791. X    LONG count;
  1792. X    LONG *pargs;
  1793. X    LONG res1 = NULL;
  1794. X
  1795. X
  1796. X    if (!(replyport = (struct MsgPort *) CreatePort(NULL, NULL)))
  1797. X    return (NULL);
  1798. X
  1799. X    packet = (struct StandardPacket *)
  1800. X    AllocMem((LONG) sizeof(*packet), MEMF_PUBLIC | MEMF_CLEAR);
  1801. X
  1802. X    if (packet)
  1803. X    {
  1804. X    packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);    /* link packet */
  1805. X    packet->sp_Pkt.dp_Link = &(packet->sp_Msg);    /* to message    */
  1806. X    packet->sp_Pkt.dp_Port = replyport;    /* set-up reply port   */
  1807. X    packet->sp_Pkt.dp_Type = type;    /* what to do... */
  1808. X
  1809. X    /* move all the arguments to the packet */
  1810. X    pargs = &(packet->sp_Pkt.dp_Arg1);    /* address of first
  1811. X                         * argument */
  1812. X    for (count = 0; (count < nargs) && (count < 7); count++)
  1813. X        pargs[count] = args[count];
  1814. X
  1815. X    PutMsg(id, packet);    /* send packet */
  1816. X    WaitPort(replyport);    /* wait for packet to come back */
  1817. X    GetMsg(replyport);    /* pull message */
  1818. X
  1819. X    res1 = packet->sp_Pkt.dp_Res1;    /* get result */
  1820. X        FreeMem(packet, (LONG) sizeof(*packet));
  1821. X
  1822. X    }
  1823. X    DeletePort(replyport);
  1824. X    return (res1);
  1825. X}
  1826. X
  1827. X/*
  1828. X * Convert seconds into Amiga style time (days since 1/1/78, minutes since
  1829. X * 12AM, ticks this hour)
  1830. X */
  1831. Xstatic struct DateStamp *
  1832. Xseconds2AmiTime(long secs, struct DateStamp *ds)
  1833. X{
  1834. X    extern long timezone;
  1835. X
  1836. X    /* seconds is in GMT, so compensate */
  1837. X    secs -= timezone;
  1838. X
  1839. X    /* Subtract 8 years worth of seconds, including 2 leap years */
  1840. X    secs -= ((6 * 365) + (2 * 366)) * (60 * 60 * 24);
  1841. X
  1842. X    /* Now have seconds since 1/1/78, get days */
  1843. X    ds->ds_Days = secs / (60 * 60 * 24);
  1844. X    secs -= ds->ds_Days * (60 * 60 * 24);
  1845. X
  1846. X    /* Now have seconds since midnight, get minutes */
  1847. X    ds->ds_Minute = secs / 60;
  1848. X    secs -= ds->ds_Minute * 60;
  1849. X
  1850. X    /* Now have seconds this minute, convert to ticks */
  1851. X    ds->ds_Tick = secs * 50;
  1852. X    return(ds);
  1853. X}
  1854. END_OF_FILE
  1855. if test 4532 -ne `wc -c <'utime.c'`; then
  1856.     echo shar: \"'utime.c'\" unpacked with wrong size!
  1857. fi
  1858. # end of 'utime.c'
  1859. fi
  1860. if test -f 'wildmat.c' -a "${1}" != "-c" ; then 
  1861.   echo shar: Will not clobber existing file \"'wildmat.c'\"
  1862. else
  1863. echo shar: Extracting \"'wildmat.c'\" \(3462 characters\)
  1864. sed "s/^X//" >'wildmat.c' <<'END_OF_FILE'
  1865. X/*
  1866. X * @(#)wildmat.c 1.3 87/11/06    Public Domain.
  1867. X *
  1868. XFrom: rs@mirror.TMC.COM (Rich Salz)
  1869. XNewsgroups: net.sources
  1870. XSubject: Small shell-style pattern matcher
  1871. XMessage-ID: <596@mirror.TMC.COM>
  1872. XDate: 27 Nov 86 00:06:40 GMT
  1873. X
  1874. XThere have been several regular-expression subroutines and one or two
  1875. Xfilename-globbing routines in mod.sources.  They handle lots of
  1876. Xcomplicated patterns.  This small piece of code handles the *?[]\
  1877. Xwildcard characters the way the standard Unix(tm) shells do, with the
  1878. Xaddition that "[^.....]" is an inverse character class -- it matches
  1879. Xany character not in the range ".....".  Read the comments for more
  1880. Xinfo.
  1881. X
  1882. XFor my application, I had first ripped off a copy of the "glob" routine
  1883. Xfrom within the find(1) source, but that code is bad news:  it recurses
  1884. Xon every character in the pattern.  I'm putting this replacement in the
  1885. Xpublic domain.  It's small, tight, and iterative.  Compile with -DTEST
  1886. Xto get a test driver.  After you're convinced it works, install in
  1887. Xwhatever way is appropriate for you.
  1888. X
  1889. XI would like to hear of bugs, but am not interested in additions; if I
  1890. Xwere, I'd use the code I mentioned above.
  1891. X*/
  1892. X/*
  1893. X**  Do shell-style pattern matching for ?, \, [], and * characters.
  1894. X**  Might not be robust in face of malformed patterns; e.g., "foo[a-"
  1895. X**  could cause a segmentation violation.
  1896. X**
  1897. X**  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
  1898. X*/
  1899. X
  1900. X/*
  1901. X * Modified 6Nov87 by John Gilmore (hoptoad!gnu) to return a "match"
  1902. X * if the pattern is immediately followed by a "/", as well as \0.
  1903. X * This matches what "tar" does for matching whole subdirectories.
  1904. X *
  1905. X * The "*" code could be sped up by only recursing one level instead
  1906. X * of two for each trial pattern, perhaps, and not recursing at all
  1907. X * if a literal match of the next 2 chars would fail.
  1908. X */
  1909. X#define TRUE        1
  1910. X#define FALSE        0
  1911. X
  1912. X
  1913. Xstatic int
  1914. XStar(s, p)
  1915. X    register char    *s;
  1916. X    register char    *p;
  1917. X{
  1918. X    while (wildmat(s, p) == FALSE)
  1919. X    if (*++s == '\0')
  1920. X        return(FALSE);
  1921. X    return(TRUE);
  1922. X}
  1923. X
  1924. X
  1925. Xint
  1926. Xwildmat(s, p)
  1927. X    register char    *s;
  1928. X    register char    *p;
  1929. X{
  1930. X    register int      last;
  1931. X    register int      matched;
  1932. X    register int      reverse;
  1933. X
  1934. X    for ( ; *p; s++, p++)
  1935. X    switch (*p) {
  1936. X        case '\\':
  1937. X        /* Literal match with following character; fall through. */
  1938. X        p++;
  1939. X        default:
  1940. X        if (*s != *p)
  1941. X            return(FALSE);
  1942. X        continue;
  1943. X        case '?':
  1944. X        /* Match anything. */
  1945. X        if (*s == '\0')
  1946. X            return(FALSE);
  1947. X        continue;
  1948. X        case '*':
  1949. X        /* Trailing star matches everything. */
  1950. X        return(*++p ? Star(s, p) : TRUE);
  1951. X        case '[':
  1952. X        /* [^....] means inverse character class. */
  1953. X        if (reverse = p[1] == '^')
  1954. X            p++;
  1955. X        for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
  1956. X            /* This next line requires a good C compiler. */
  1957. X            if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
  1958. X            matched = TRUE;
  1959. X        if (matched == reverse)
  1960. X            return(FALSE);
  1961. X        continue;
  1962. X    }
  1963. X
  1964. X    /* For "tar" use, matches that end at a slash also work. --hoptoad!gnu */
  1965. X    return(*s == '\0' || *s == '/');
  1966. X}
  1967. X
  1968. X
  1969. X#ifdef    TEST
  1970. X#include <stdio.h>
  1971. X
  1972. Xextern char    *gets();
  1973. X
  1974. X
  1975. Xmain()
  1976. X{
  1977. X    char     pattern[80];
  1978. X    char     text[80];
  1979. X
  1980. X    while (TRUE) {
  1981. X    printf("Enter pattern:  ");
  1982. X    if (gets(pattern) == NULL)
  1983. X        break;
  1984. X    while (TRUE) {
  1985. X        printf("Enter text:  ");
  1986. X        if (gets(text) == NULL)
  1987. X        exit(0);
  1988. X        if (text[0] == '\0')
  1989. X        /* Blank line; go back and get a new pattern. */
  1990. X        break;
  1991. X        printf("      %d\n", wildmat(text, pattern));
  1992. X    }
  1993. X    }
  1994. X    exit(0);
  1995. X}
  1996. X#endif    /* TEST */
  1997. END_OF_FILE
  1998. if test 3462 -ne `wc -c <'wildmat.c'`; then
  1999.     echo shar: \"'wildmat.c'\" unpacked with wrong size!
  2000. fi
  2001. # end of 'wildmat.c'
  2002. fi
  2003. echo shar: End of archive 1 \(of 5\).
  2004. cp /dev/null ark1isdone
  2005. MISSING=""
  2006. for I in 1 2 3 4 5 ; do
  2007.     if test ! -f ark${I}isdone ; then
  2008.     MISSING="${MISSING} ${I}"
  2009.     fi
  2010. done
  2011. if test "${MISSING}" = "" ; then
  2012.     echo You have unpacked all 5 archives.
  2013.     rm -f ark[1-9]isdone
  2014. else
  2015.     echo You still need to unpack the following archives:
  2016.     echo "        " ${MISSING}
  2017. fi
  2018. ##  End of shell archive.
  2019. exit 0
  2020. -- 
  2021. Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
  2022. Mail comments to the moderator at <amiga-request@cs.odu.edu>.
  2023. Post requests for sources, and general discussion to comp.sys.amiga.
  2024.